#include "kdswidget.h"
#include "ui_kdswidget.h"

#include <QScreen>
#include <QDBusConnection>
#include <QDBusInterface>
#include <QDBusReply>

#include <QFile>
#include <QDir>
#include <QStandardPaths>
#include <QtDBus/QtDBus>

#include <QJsonDocument>

#include <kwindowsystem.h>
#include <KWindowEffects>

#include <KF5/KScreen/kscreen/configmonitor.h>
#include <QPainter>
#include <QPainterPath>
#include <QDebug>

//#include "ukuistylehelper/ukuistylehelper.h"
//#include "windowmanager/windowmanager.h"

#include "expendbutton.h"
#include "clib-syslog.h"
#define TITLEHEIGHT 90
#define OPTIONSHEIGHT 70
#define BOTTOMHEIGHT 60


#define QT_THEME_SCHEMA             "org.ukui.style"

enum {
    FIRSTSCREEN,
    CLONESCREEN,
    EXTENDSCREEN,
    OTHERSCREEN,
    ALLMODES,
};

bool operator<(const QSize &s1, const QSize &s2)
{
    return s1.width() * s1.height() < s2.width() * s2.height();
}

template<>
bool qMapLessThanKey(const QSize &s1, const QSize &s2)
{
    return s1 < s2;
}

QString KDSWidget::mConfigsDirName = QStringLiteral("" /*"configs/"*/); // TODO: KDE6 - move these files into the subfolder

KDSWidget::KDSWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::KDSWidget)
{
    ui->setupUi(this);

    btnsGroup = new QButtonGroup;
    if(QGSettings::isSchemaInstalled(QT_THEME_SCHEMA))
    {
        m_styleSettings = new QGSettings(QT_THEME_SCHEMA);
    }
    ukcciface = new QDBusInterface("org.ukui.ukcc.session",
                                   "/",
                                   "org.ukui.ukcc.session.interface",
                                   QDBusConnection::sessionBus());
}

KDSWidget::~KDSWidget()
{
    delete ui;

    delete ukcciface;
}

void KDSWidget::beginSetupKF5(){
    QObject::connect(new KScreen::GetConfigOperation(), &KScreen::GetConfigOperation::finished,
                     [&](KScreen::ConfigOperation *op) {
        setConfig(qobject_cast<KScreen::GetConfigOperation*>(op)->config());
    });
    setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);

    setAttribute(Qt::WA_TranslucentBackground, true);
    this->setProperty("useStyleWindowManager", false);

    /* 不在任务栏显示图标 */
    KWindowSystem::setState(winId(), NET::SkipTaskbar | NET::SkipPager);
    /*主屏变化处理*/
    connect(QApplication::primaryScreen(), &QScreen::geometryChanged, this, &KDSWidget::geometryChangedHandle);

    connect(KWindowSystem::self(), &KWindowSystem::activeWindowChanged, this,[&](WId activeWindowId) {
        if (activeWindowId != this->winId()) {
            close();
        }
    });
}

void KDSWidget::setupComponent(){

    const QString style = m_styleSettings->get("style-name").toString();

    ui->outputPrimaryTip->hide();

    for (int i = 0; i < ALLMODES; i++){
        ExpendButton * btn = new ExpendButton();
        btn->setFixedHeight(70);
        btnsGroup->addButton(btn, i);

        switch (i) {
        case FIRSTSCREEN:
            btn->setSign(FIRSTSCREEN % 2,style);
            btn->setBtnText(tr("First Display"));
            btn->setBtnLogo(":/img/main.png",style);
            break;
        case CLONESCREEN:
            btn->setSign(CLONESCREEN % 2,style);
            btn->setBtnText(tr("Mirror Display"));
            btn->setBtnLogo(":/img/clone.png",style);
            break;
        case EXTENDSCREEN:
            btn->setSign(EXTENDSCREEN % 2,style);
            btn->setBtnText(tr("Extend Display"));
            btn->setBtnLogo(":/img/extend.png",style);
            break;
        case OTHERSCREEN:
            btn->setSign(OTHERSCREEN % 2,style);
            btn->setBtnText(tr("Vice Display"));
            btn->setBtnLogo(":/img/vice.png",style);
            break;
        default:
            break;
        }

        ui->btnsVerLayout->addWidget(btn);
    }

    int h = TITLEHEIGHT + OPTIONSHEIGHT * ALLMODES + BOTTOMHEIGHT;
    setFixedWidth(384);
    setFixedHeight(h);

    m_qssDefaultOrDark = ("QWidget#titleWidget{background: transparent;}"\
                          "QWidget#bottomWidget{background: transparent; border: none;}"\
                          "QLabel#titleLabel{color: #FFFFFF;background: transparent; }"\
                          );

    m_qssLight = ("QWidget#titleWidget{background: transparent; border: none;}"\
                  "QWidget#bottomWidget{background: transparent; border: none; }"\
                  "QLabel#titleLabel{color: #232426;background: transparent;}"\
                  );
    /*跟随系统字体变化*/
    int fontSize = m_styleSettings->get("system-font-size").toInt();
    QFont font;
    font.setPointSize(fontSize + 4);
    ui->titleLabel->setFont(font);
}

void KDSWidget::setupConnect()
{
    connect(btnsGroup, static_cast<void(QButtonGroup::*)(int)>(&QButtonGroup::buttonClicked), this, [=](int id){

        qDebug()<<"buttonClicked Current Id"<<id;
        USD_LOG(LOG_DEBUG,"buttonClicked current id :%d",id);

        selectid = id;

        switch (id) {
        case TurnOffExternal:
            ukcciface->call("setScreenMode", "first");
            executeCommand("kscreen-doctor","first");
            setCurrentUIStatus(TurnOffExternal);
            USD_LOG(LOG_DEBUG,"kscreen-doctor -m first");

            close();
            break;
        case Clone:
            ukcciface->call("setScreenMode", "copy");
            executeCommand("kscreen-doctor","clone");
            setCurrentUIStatus(Clone);
            USD_LOG(LOG_DEBUG,"kscreen-doctor -m clone");

            close();
            break;
        case ExtendToRight:
            ukcciface->call("setScreenMode", "expand");
            executeCommand("kscreen-doctor","extend");
            setCurrentUIStatus(ExtendToRight);
            USD_LOG(LOG_DEBUG,"kscreen-doctor -m extend");

            close();
            break;
        case TurnOffEmbedded:
            USD_LOG(LOG_DEBUG,"kscreen-doctor -m other");
            ukcciface->call("setScreenMode", "second");
            executeCommand("kscreen-doctor","other");
            setCurrentUIStatus(TurnOffEmbedded);

            close();
            break;
        default:
            break;
        }

    });
}

void KDSWidget::executeCommand(QString cmd,QString paramter)
{
    QStringList str;
    str<<"-m"<<paramter;
    /*调用kscreeen命令低概率失效问题，临时方案，连续多次调用*/
    QProcess::startDetached(cmd,str);
//    QProcess::startDetached(cmd,str);
//    QProcess::startDetached(cmd,str);
//    QProcess::startDetached(cmd,str);
}

int KDSWidget::getCurrentStatus()
{
    QString firstOutputName;

    const KScreen::ConfigPtr &config = this->currentConfig();

    const KScreen::OutputList &outputs = config->connectedOutputs();

    firstOutputName = findFirstOutput();

    if (outputs.count() < 2){
        return FIRSTSCREEN;
    } else {
        /* output.data()->clones().isEmpty() is not valid */
        Q_FOREACH(const KScreen::OutputPtr &output, outputs) {

            if (QString::compare(firstOutputName, output.data()->name()) == 0){
                if (!output.data()->isEnabled()){
                    return OTHERSCREEN;
                }
            }

            if (!output.data()->isEnabled()){
                return FIRSTSCREEN;
            }
        }

        Q_FOREACH(const KScreen::OutputPtr &output, outputs) {
            if (output.data()->pos().x() != 0){
                return EXTENDSCREEN;
            }
        }

        return CLONESCREEN;
    }
}

void KDSWidget::setCurrentUIStatus(int id){
    //set all no checked
//    currentid = id;
    for (QAbstractButton * button : btnsGroup->buttons()){
        ExpendButton * btn = dynamic_cast<ExpendButton *>(button);

        btn->setBtnChecked(false);

        if (id == btnsGroup->id(button)){
            btn->setBtnChecked(true);
            btn->setChecked(true);
        }
    }

    // status == -1
    if (id == -1){
        ExpendButton * btn1 = dynamic_cast<ExpendButton *>(btnsGroup->button(FIRSTSCREEN));
        btn1->setChecked(true);
    }
}

void KDSWidget::setConfig(const KScreen::ConfigPtr &config)
{
    mConfig = config;
    KScreen::ConfigMonitor::instance()->addConfig(mConfig);

    setupComponent();
    setupConnect();
    currentid = getCurrentStatus();
    setCurrentUIStatus(currentid);
    show();
    geometryChangedHandle();
}

KScreen::ConfigPtr KDSWidget::currentConfig() const {

    return mConfig;
}

QString KDSWidget::findFirstOutput()
{

    int firstopID = -1;
    QString firstopName;

    const KScreen::ConfigPtr &config = this->currentConfig();

    Q_FOREACH(const KScreen::OutputPtr &output, config->connectedOutputs()) {
        if (firstopID == -1){
            firstopID = output.data()->id();
            firstopName = output.data()->name();
        }
        if (firstopID > output.data()->id()){
            firstopID = output.data()->id();
            firstopName = output.data()->name();
        }
    }

    return firstopName;
}


void KDSWidget::geometryChangedHandle()
{
    int x=QApplication::primaryScreen()->geometry().x();
    int y=QApplication::primaryScreen()->geometry().y();
    int width = QApplication::primaryScreen()->size().width();
    int height = QApplication::primaryScreen()->size().height();
    int ax,ay;
    ax = x+(width - this->width())/2;
    ay = y+(height - this->height())/2;
    move(ax, ay);
//    kdk::WindowManager::setGeometry(this->windowHandle(),QRect(ax,ay,this->width(),this->height()));

    QTimer::singleShot(100, this, [=](){
        QObject::connect(new KScreen::GetConfigOperation(), &KScreen::GetConfigOperation::finished,
                         [&](KScreen::ConfigOperation *op) {
            mConfig = qobject_cast<KScreen::GetConfigOperation*>(op)->config();
            setCurrentUIStatus(getCurrentStatus());
        });
    });
}


void KDSWidget::nextSelectedOption(){
    int current = btnsGroup->checkedId();
    int next;

    /* no button checked */
//    if (current == -1)
//        ;

    next = current == ALLMODES - 1 ? 0 : current + 1;

    ExpendButton * btn = dynamic_cast<ExpendButton *>(btnsGroup->button(next));
    btn->setChecked(true);
}

void KDSWidget::lastSelectedOption(){
    int current = btnsGroup->checkedId();
    int last;

    /* no button checked */
    if (current == -1)
        current = ALLMODES;

    last = current == 0 ? ALLMODES - 1 : current - 1;

    ExpendButton * btn = dynamic_cast<ExpendButton *>(btnsGroup->button(last));
    btn->setChecked(true);
}

void KDSWidget::confirmCurrentOption(){
    int current = btnsGroup->checkedId();
    if (current == -1)
        return;

    ExpendButton * btn = dynamic_cast<ExpendButton *>(btnsGroup->button(current));
//    btn->click();
    btn->animateClick();
}

void KDSWidget::closeApp(){
    close();
}

void KDSWidget::msgReceiveAnotherOne(const QString &msg){
//    qDebug() << "another one " << msg;
    nextSelectedOption();
}

void KDSWidget::keyPressEvent(QKeyEvent* event)
{
    switch (event->key())
    {
    case Qt::Key_Up:
        lastSelectedOption();
        break;
    case Qt::Key_Down:
        nextSelectedOption();
        break;
    case Qt::Key_Return:
    case Qt::Key_Enter:
        confirmCurrentOption();
        break;
    case Qt::Key_Meta:
    case Qt::Key_Super_L:
        break;
    default:
        close();
        break;
    }
}


void KDSWidget::showEvent(QShowEvent* event)
{
    if(m_styleSettings->get("style-name").toString() == "ukui-light")
    {
        setStyleSheet(m_qssLight);
        setPalette(QPalette(QColor("#FFFFFF")));//设置窗口背景色

    } else {
        setPalette(QPalette(QColor("#40232426")));//设置窗口背景色
        setStyleSheet(m_qssDefaultOrDark);

    }
}


void KDSWidget::paintEvent(QPaintEvent *event)
{
    QRect rect = this->rect();
    QPainterPath path;

    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);  //反锯齿;
    painter.setPen(Qt::transparent);
    qreal radius=24;
    path.moveTo(rect.topRight() - QPointF(radius, 0));
    path.lineTo(rect.topLeft() + QPointF(radius, 0));
    path.quadTo(rect.topLeft(), rect.topLeft() + QPointF(0, radius));
    path.lineTo(rect.bottomLeft() + QPointF(0, -radius));
    path.quadTo(rect.bottomLeft(), rect.bottomLeft() + QPointF(radius, 0));
    path.lineTo(rect.bottomRight() - QPointF(radius, 0));
    path.quadTo(rect.bottomRight(), rect.bottomRight() + QPointF(0, -radius));
    path.lineTo(rect.topRight() + QPointF(0, radius));
    path.quadTo(rect.topRight(), rect.topRight() + QPointF(-radius, -0));

    painter.setBrush(palette().base());
    painter.setPen(Qt::transparent);
    painter.setOpacity(0.75);
    painter.drawPath(path);

    KWindowEffects::enableBlurBehind(this->winId(), true, QRegion(path.toFillPolygon().toPolygon()));
    QWidget::paintEvent(event);
}
